/*
 * piece.h
 *
 *  Created on: 2012-12-5
 *      Author: shane
 */

#ifndef PIECE_H_
#define PIECE_H_
#include "boundary.h"
#include <complex>
#include<vector>
#include<algorithm>
#include "../pattern.h"
namespace EME
{

/**The data structure for the fields
 * Here, this is only the base abstract class, which should not be created directly
 * Basic configurations and structure for one piece in z direction is described and included
 */
class piece
{
protected:
	double xmin;
	double xmax;
	double ymin;
	double ymax;
	pattern *ptn;
	boundary boundary_condition;
	unsigned int num_modes; ///< Actually is mode pair number for bidirectional modes
	bool if_calculated; ///< if already calculated, if not, will trigger auto-calculation when idle.
public:
	///Simple constructor so that each parameters was initialized with input ones
	inline piece(const double& xmin_in, const double& xmax_in,
			const double& ymin_in, const double& ymax_in,
			pattern * const ptn_in, const boundary& boundary_condition_in,
			const unsigned int& num_modes_in, const bool& if_calculated_in) :
			xmin(xmin_in), xmax(xmax_in), ymin(ymin_in), ymax(ymax_in), ptn(
					ptn_in), boundary_condition(boundary_condition_in), num_modes(
					num_modes_in), if_calculated(if_calculated_in)
	{
	}
	;
	///copy constructor and just same as the default one
	inline piece(const piece& B) :
			xmin(B.xmin), xmax(B.xmax), ymin(B.ymin), ymax(B.ymax), ptn(B.ptn), boundary_condition(
					B.boundary_condition), num_modes(B.num_modes), if_calculated(
					B.if_calculated)
	{
	}
	;
	virtual int solve()=0;
	virtual ~piece()
	{
	}
	;
	virtual double normalization(const unsigned int& n)=0;
	virtual std::complex<double> projection(const unsigned int& na,
			const int& za, const piece& B, const unsigned int& nb,
			const int& zb)=0; ///< Mode overlapping, z=1 for +z and -1 for -z
};
/**For rectangular element
 * basic operation for usage in simple_piece class
 */
class rect_element
{
public:
	double xmin;
	double xmax;
	double ymin;
	double ymax;
	inline rect_element(const double& xcent, const double& ycent,
			const double& dx, const double& dy, const int& a) :
			xmin(xcent - 0.5 * dx), xmax(xcent + 0.5 * dx), ymin(
					ycent - 0.5 * dy), ymax(ycent + 0.5 * dy)
	{
	}
	;
	inline rect_element(const double& xmin_in, const double& xmax_in,
			const double& ymin_in, const double& ymax_in) :
			xmin(xmin_in), xmax(xmax_in), ymin(ymin_in), ymax(ymax_in)
	{
	}
	;
	static inline double overlap(rect_element& A, rect_element& B)
	{
		double x = std::min(A.xmax, B.xmax) - std::max(A.xmin, B.xmin);
		double y = std::min(A.ymax, B.ymax) - std::max(A.ymin, B.ymin);
		return (x > 0. ? x : 0.) * (y > 0. ? y : 0.);
	}
	;
	inline double overlap(rect_element &B)
	{
		return overlap(*this, B);
	}
	;
};
/**For rectangular grids,simple and easy to use
 * However, this class will not deal with the geometry
 * It only receives epsilon configuration and returns its field distribution
 */
class simple_piece: public piece
{
protected:
	unsigned int nx;
	unsigned int ny;
	std::vector<std::complex<double>*> ex;
	std::vector<std::complex<double>*> ey;
	std::vector<std::complex<double>*> ez;
	std::vector<std::complex<double>*> hx;
	std::vector<std::complex<double>*> hy;
	std::vector<std::complex<double>*> hz;
public:
	///The most common constructor calls to input the epsilon configuration, for non-calculated situation
	simple_piece(const double& xmin_in, const double& xmax_in,
			const double& ymin_in, const double& ymax_in,
			const boundary& boundary_condition_in,
			const unsigned int& num_modes_in, const unsigned int& nx_in,
			const unsigned int& ny_in, pattern * const ptn_in);
	simple_piece(const simple_piece& B);
	virtual double normalization(unsigned int n);
	virtual std::complex<double> projection(unsigned int na, signed char za,
			piece& B, unsigned int nb, signed char zb); //< check what is the type of B and run the corresponding function
	std::complex<double> projection(unsigned int na, signed char za,
			simple_piece& B, unsigned int nb, signed char zb); //< projection between two simple pieces, however, maybe in different resolution
	virtual ~simple_piece();
};

}

#endif /* PIECE_H_ */
